02|一条SQL更新语句是如何执行的

执行流程(和查询流程保持一致)

  • 连接器 –> 连接数据库
  • 分析器 –> 词法和语法分析这是一条更新语句
  • 优化器 –> 决定使用哪个索引
  • 执行器 –> 找到具体的某一行,然后更新

日志模块

SQL更新过程中涉及两个重要的日志模块

redo log(重做日志)

  • WHAT
    redo log(重做日志)类似于掌柜账本记账的模式,先记账(先写日志),后清账(再写磁盘)
  • WHY
    mysql的每一次更新过程IO成本和查找成本很高。每一次更新操作都要在磁盘中找到对应的记录然后更新。当更新比较频繁的时候,性能就非常的不好。
  • HOW
    当一条记录需要更新的时候:
  1. InnoDB引擎先把记录写到redo log
  2. 更新内存
  3. InnoDB引擎在系统空闲的时候,将操作记录更新到磁盘中

PS:

  • redo log是InnoDB特有的日志
  • 如果更新特别频繁,redo log特别多,系统会放下工作,将一部分redo log的任务更新到磁盘中,为redo log腾出空间
  • redo log是固定大小的,可以配置一组四个文件,每个文件1GB, 从头开始写,写到末尾然后继续回到开头写
  • InnoDB 可以依靠redo log保证数据库发生异常重启的时候,之前的记录不会丢失(crash-safe)

binlog(归档日志)

bin log是server层实现的日志,可以应用于所有存储引擎

redolog与binlog的区别

  • redolog是InnoDB独有, binlog是Server层实现的,所有引擎都可以使用
  • redolog是物理日志,记录某个数据页做了什么改动,binlog是逻辑日志,记录语句的原始逻辑
  • redolog是循环写,空间固定会用完,binlog可以最佳写入,并不会覆盖以前的日志。

update语句执行的内部流程

  1. 执行器通过引擎找到对应的记录。如果这一行所在数据页在内存中,引擎就从内存中取,否则就从磁盘读入。
  2. 执行器拿到对应的数据,进行更新,然后调用引擎接口写入数据
  3. 引擎将数据更新到内存,同时将更新操作记录到redo日志,此时redo log处于prepare状态,告知执行器执行完成。
  4. 执行器生成binlog,并将binlog写入磁盘
  5. 执行器调用引擎的提交事务接口,引擎将写入的redo log改成提交状态

以上的流程包含了一个两阶段提交

两阶段提交

  • what
    保证redolog与binlog的数据逻辑一致性。
  1. 先写redolog后写binlog
    redolog写完,binlog还没写完的时候,MySQL异常重启,可以通过redolog将记录恢复。但是当我们需要通过binlog恢复临时库的时候,由于binlog丢失,临时库的数据会少一次更新操作
  2. 先写binlog厚些redolog
    binlog写完,redolog还没写,系统崩溃之后,由此数据没有被更新。但是binlog已经有了更新的日志,之后用binlog来恢复数据的时候就多了一条更新。